/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_zml.htm
 *
 * Zhiqim Zml is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.zml.expression.primitive;

import org.zhiqim.kernel.Z;
import org.zhiqim.kernel.annotation.AnGlobal;
import org.zhiqim.kernel.util.Classes;
import org.zhiqim.zml.ZmlEngine;
import org.zhiqim.zml.ZmlVariable;
import org.zhiqim.zml.exception.ExpressionException;
import org.zhiqim.zml.exception.PropertNotExistException;
import org.zhiqim.zml.expression.Primitive;
import org.zhiqim.zml.expression.operator._Property;

/**
 * 变量原型，格式为字母或下划线开头，(字母、下划线和数字)连贯
 *
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 * @version v1.0.1 @author zouzhigang 2015-10-22 增加对AnAlias,AnStatic,AnGlobal,AnNew的支持
 * @version v1.2.2 @author zhichenggang 2016-12-21 删除AnStatic的支持，修改为增加buildClass当是类结构但不是AnGlobal,AnNew时再检查调用
 * @version v1.4.0 @author zouzhigang 2018-01-19 删除对AnNew的支持，AnNew定义为必须前缀new的别名对象
 */
public class _Variable extends Primitive
{
    private String value;
    private Class<?> cls;
    
    public _Variable(String value)
    {
        this.value = value;
    }
    
    /** 重新设置值 */
    public void setValue(String value)
    {
        this.value = value;
    }
    
    @Override
    public int getType()
    {
        return VARIABLE;
    }
    
    @Override
    public Object build(ZmlVariable variableMap) throws ExpressionException
    {
        //1.判断是不是变量，如果是返回变量值
        Object instance = variableMap.get(value);
        if (instance != null)
            return instance;
        
        //2.判断是否是java系统类名String,List等
        Class<?> cls = ZmlEngine.getJavaClass(value);
        if (cls != null)
        {
            //认为是通过类去调用静态属性或方式，直接返回null，调用者再从buildClass获取clazz去调用
            this.cls = cls;
            return null;
        }
        
        //3.判断是否是AnAlias别名定义的类名，如Validates,DateTimes
        cls = Z.cls().get(value);
        if (cls != null)
        {
            return returnAliasInstance(cls);
        }
        
        //4.判断是否是属性，即variable.property方式
        int lastIndex = value.lastIndexOf(".");
        if (lastIndex != -1)
        {
            String name = value.substring(0, lastIndex);
            String prop = value.substring(lastIndex+1);
            
            try
            {
                return new _Property(name, prop).build(variableMap);
            }
            catch(PropertNotExistException e)
            {
                //属性未找到则不返回
            }
        }
        
        //5.最后认为是类全称，如org.zhiqim.kernel.util.Validates全名，或没有包名的类，如ATest
        cls = Classes.forName(value);
        if (cls != null)
        {//最少可能且最慢放最后
            return returnAliasInstance(cls);
        }

        //都不对，就没办法了啦！
        return null;
    }
    
    /** 在_Method中当build为null时再检查是否是调用静态方法 */
    public Class<?> buildClass()
    {
        return this.cls;
    }
    
    private Object returnAliasInstance(Class<?> cls)
    {
        if (cls.isAnnotationPresent(AnGlobal.class))
        {//定义了AnGlobal
            return Z.glb().getc(cls);
        }
        
        //其他的认为是通过类去调用静态属性或方式，直接返回null，调用者再从buildClass
        this.cls = cls;
        return null;
    }
    
    @Override
    public String toString()
    {
        return value;
    }

    public String getValue()
    {
        return value;
    }
}
